#include "fstree.hpp"
#include "common.hpp"
#include "fs.hpp"

FSTree::FSTree(FS *argFS)
{
	fs = argFS;
}


static char *colnames = { "name" };
QVariant FSTree::headerData(int, Qt::Orientation orientation, int role) const
{
	if( (orientation == Qt::Horizontal) && (role == Qt::DisplayRole))
		return colnames[0];
	else
		return QVariant();
}

int FSTree::columnCount(const QModelIndex&) const
{
	return 1;
}

QString FSTree::filePath(const QModelIndex& index) const
{
	if(index.isValid() && inbounds(index.internalId(), 0, pathList.size())){
		return pathList[index.internalId()];
	}
	return QDir::separator();
}

QStringList FSTree::entryList(QString &path) const
{
	return fs->entryList(path, QDir::Dirs | QDir::NoDotAndDotDot);
}

int FSTree::rowCount(const QModelIndex &parent) const
{	
	QString path = filePath(parent);
	QStringList list = entryList(path);
	int count = list.size();
	return count;
}

static bool isParent(QString parent, QString path)
{
	QStringList sl = path.split(QDir::separator());
	while(!sl.isEmpty()){
		QString path = sl.join(QDir::separator());
		if(parent == path)
			return true;
		sl.takeLast();
	}
	return false;
}

static bool isContainParent(QSet<QString> set, QString path)
{
	foreach(QString it, set){
		if(isParent(it, path))
			return true;
	}
	return false;
}

static bool isContainChild(QSet<QString> set, QString path)
{
	foreach(QString it, set){
		if(isParent(path, it))
			return true;
	}
	return false;
}

QVariant FSTree::data(const QModelIndex& index, int role) const
{
	if( !index.isValid() )
		return QVariant();
	
	if( role == Qt::DisplayRole 
		&& inbounds(index.internalId(), 0, pathList.size())){
		QStringList plist = pathList[index.internalId()].split(QDir::separator(), QString::SkipEmptyParts);
		QVariant res = plist.size() ? plist.takeLast() : QVariant();
		return res;
	}
	else if ( role == Qt::CheckStateRole ){
		QString path = pathList[index.internalId()];
		if(isContainParent(activePaths, path))
			return Qt::Checked;
		else if(isContainChild(activePaths, path))
			return Qt::PartiallyChecked;
		else
			return Qt::Unchecked;
	}else
		return QVariant();
}

QModelIndex FSTree::index(int row, int column, const QModelIndex& parent) const
{
	QString path = filePath(parent);
	QStringList plist = path.split(QDir::separator(), QString::SkipEmptyParts);
	QStringList flist = entryList(path);
	QModelIndex res = QModelIndex();

	if( inbounds(row, 0, flist.size()) ){
		plist << flist[row];
		QString newPath = QDir::separator() + plist.join(QDir::separator());
		newPath = QDir::cleanPath(newPath);
		if(!pathList.contains(newPath)){
			log("FSTree: added path '%s' \n", (const char*)(newPath.toLocal8Bit()) );
			pathList << newPath;
		}
		res = createIndex(row, column, pathList.indexOf(newPath));
	}

	return res;
}

QModelIndex FSTree::parent(const QModelIndex& index) const
{
	//chop path
	QString path = filePath(index);
	QStringList plist = path.split(QDir::separator(), QString::SkipEmptyParts);
	if(plist.size() < 2){
		return QModelIndex();
	}		

	//determine parentpath and parentid
	plist.takeLast();
	QString parentpath = QDir::separator() + plist.join(QDir::separator());
	parentpath = QDir::cleanPath(parentpath);
	int id = pathList.indexOf(parentpath);
	
	//get dir list, try to determine row
	QString parentname = plist.takeLast();
	QString parentbase = QDir::separator() + plist.join(QDir::separator());
	QStringList flist = entryList(parentbase);
	int row = flist.indexOf(parentname);
	
	//construct new index
	QModelIndex res = createIndex(row, 0, id);

	return res;
}

void FSTree::toggleItem(const QModelIndex& index)
{
	QString name = pathList[index.internalId()];
	const char *cpath = name.toLocal8Bit();
	log("FS: activated %s\n", cpath);

	if( activePaths.contains(name) )
		activePaths.remove(name);
	else{
		foreach(QString it, activePaths){
			if(isParent(name, it))
				activePaths.remove(it);
		}
		activePaths.insert(name);
	}

	emit layoutChanged();
}

QList<QString> FSTree::getSelected() const
{
	return activePaths.toList();
}
